
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>[k8s] kubernetes从harbor拉取镜像没有权限解决方法 unauthorized</title>
            </head>
            <body>
            <a href="https://andyoung.blog.csdn.net">原作者博客</a>
            <div id="content_views" class="markdown_views prism-atom-one-light">
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                    <p>Kubernetes在拉取私服(<a href="https://blog.csdn.net/agonie201218/article/details/115691894">Harbor</a>)镜像时，经常出现问题，导致ImagePullBackOff。查看kubectl describe pod …，还经常发现这类错误：</p> 
<blockquote> 
 <p>Failed to pull image “192.168.1.13:9080/ces/ces-gateway:1.1-SNAPSHOT”: rpc error: code = Unknown desc = Error response from daemon: unauthorized: unauthorized to access repository: ces/ces-gateway, action: pull: unauthorized to access repository: ces/ces-gateway, action: pull</p> 
</blockquote> 
<p>又或者：</p> 
<blockquote> 
 <p>Failed create pod sandbox: rpc error: code = Unknown desc = failed pulling image …Error response from daemon: pull access denied for …repository does not exist or may require ‘docker login’</p> 
</blockquote> 
<p>这是因为没有正确配置pull权限所致。</p> 
<h3><a id="dockerconfigjson_15"></a><strong>~/.docker/config.json无效</strong></h3> 
<p>首先，不要寄望于~/.docker/config.json。与Docker Swarm不同，Kubernetes不会使用这里的配置来pull。</p> 
<p>当然，用docker login测试过账户、密码、Registry、镜像均无误后，再走下一步，是更好的选择。</p> 
<h3><a id="imagePullSecrets_21"></a><strong>使用</strong><code>imagePullSecrets</code></h3> 
<p>通过创建docker-registry类的secrets，可以实现类似docker login的功能。</p> 
<blockquote> 
 <p>regcred secrets 名称</p> 
</blockquote> 
<pre><code>kubectl create secret docker-registry regcred \    
--docker-server= \    
--docker-username= \    
--docker-password= \    
--docker-email=
</code></pre> 
<p>其中.dockerconfigjson的值包含了登录harbor的用户名和密码等信息，通过以下命令进行查看：</p> 
<p><code>kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d</code></p> 
<p>其中，server、username和password都是必填项，email可以不填。</p> 
<p>在使用时，把imagePullSecrets添加到Pod配置中。</p> 
<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container
    image: your-private-image
  imagePullSecrets:
  - name: regcred
</code></pre> 
<p>其中，regcred为secrets名称，可随意指定。</p> 
<h3><a id="Namespace_56"></a><strong>注意Namespace</strong></h3> 
<p>即使创建了secrets、配置了imagePullSecrets，有时仍然无法pull镜像。比如Calico的相关镜像，如果被同步到了本地一个私有Registry中，一般配置时无效的。</p> 
<p>这是因为，Calico属于系统Network组件，Namespace是kube-system。而一般创建的secrets，属于default。通过以下命令可以查看特定secrets的详细信息。</p> 
<pre><code># kubectl get secret regcred -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodHRwOi8vaGFyYm9yLnR1cmluZy1jaS5oaXNpbGljb24uY29tIjp7IlVzZXJuYW1lIjoiY2hyaXN0b3BoZXIiLCJQYXNzd29yZCI6IlFpZGRZYWZkQmF2YTYjIiwiRW1haWwiOiJ5MDA0NDU0ODBAbm90ZXNtYWlsLmh1YXdlaS5jb20ifX19
kind: Secret
metadata:
  creationTimestamp: "2019-01-10T08:51:03Z"
  name: regcred
namespace: default
  resourceVersion: "100110"
  selfLink: /api/v1/namespaces/default/secrets/regcred
  uid: dc96580b-14b4-11e9-9f81-e435c87f8d90
type: kubernetes.io/dockerconfigjson
</code></pre> 
<p>在创建secrets时需要指定Namespace：</p> 
<pre><code>kubectl --namespace kube-system \
    create secret docker-registry regcred \
    --docker-server= \
    --docker-username= \
    --docker-password= \
    --docker-email=
</code></pre> 
<p>不同Namespace，secrets可以同名，所以仍然可以叫regcred。</p> 
<p>注意：或者，在secrets创建后可以修改一些内容：</p> 
<pre><code>kubectl edit secret regcred --namespace=kube-system
</code></pre> 
<p>但不能修改Namespace。所以，必须在创建时准确指定。</p> 
<h3><a id="patchimagePullSecrets_105"></a><strong>用patch避免设置</strong><code>imagePullSecrets</code></h3> 
<p>每个私有镜像在使用前，都需要设置imagePullSecrets，这是一件非常繁琐的事。在迁移服务时，它能有效地提醒secrets的迁移。这是一个优点，但能被良好的迁移文档所解决。</p> 
<p>用patch可以避免这么繁琐。</p> 
<pre><code>kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "regcred"}]}'
</code></pre> 
<p>这相当于，在default这个Namespace中的所有镜像pull操作，都自动具备了regcred这个账户密码。</p> 
<p>终于，和docker login一样了。</p> 
<p>注意：这里的示例只针对default这个Namespace。其它的Namespace需要一一执行patch。某些场景下，比如网络组件Calico，似乎只能老老实实地写imagePullSecrets。</p> 
<h3><a id="k8s_123"></a><strong>对k8s系统镜像无效</strong></h3> 
<p>系统镜像中，kube-proxy、pause是在所有Slave节点都需要使用的。如果这些系统镜像被设为私有，则无法下载。以上方法无效，原因不明。</p> 
<p>所以，k8s系统镜像，即使同步到了本地Registry，也不要设为私有。</p>
                </div>
            </body>
            </html>
            